/**
 * Copyright: Copyright (c) 2018, 2022
 * Company: 杭州叙简科技股份有限公司
 */
package cn.com.scooper.impl.core;

import cn.com.scooper.dao.core.AccountDao;
import cn.com.scooper.pojo.core.AccountBo;
import cn.com.scooper.pojo.core.AccountDo;
import cn.com.scooper.service.core.CoreService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 核心服务，和scooper-core相关的服务。<br />
 * token有效性验证这里直接操作数据，当然也可以调用redis的scooper-core服务去检测，但是内部使用没有必要引入redis，增加了不少复杂性。
 * 当前这种机制存在缺陷，期待平台程序下个版本升级后采用 JWT 或者 OAuth2 Token方案， 来简化各子系统的token验证。
 *
 * @author LuLihong
 * @date 2017-12-29
 **/
@Service
public class CoreServiceImpl implements CoreService {
    private static final Logger LOGGER= LoggerFactory.getLogger(CoreServiceImpl.class);

    @Autowired(required = false)
    private AccountDao accountDao;

    /**
     * 存储token和账号信息的映射关系
     */
    private Map<String, AccountBo> accountMap = new ConcurrentHashMap<>();

    private Map<String, String> usernameMap = new ConcurrentHashMap<>();


    /**
     * 根据token获取用户信息
     *
     * @param token
     * @return
     */
    @Override
    public AccountBo getAccountByToken(String token) {
        if (accountMap.containsKey(token)) {
            return accountMap.get(token);
        }

        AccountDo accountDo = accountDao.getAccountByToken(token);
        if (accountDo == null) {
            LOGGER.warn("无法找到账号信息：token=" + token);
            return null;
        }

        String accUsername = accountDo.getAccUsername();

        // 如果该账号的旧token存在，移除
        String oldToken = usernameMap.get(accUsername);
        if (oldToken != null) {
            LOGGER.info(String.format("账号[%s:%s]token发送变化：%s -> %s", accUsername, accountDo.getAccShowname(),
                    oldToken, token));
            accountMap.remove(oldToken);
        }

        AccountBo accountBo = new AccountBo(accountDo.getId(), accUsername);
        accountBo.setAccShowname(accountDo.getAccShowname());
        accountBo.setValidToken(accountDo.getValidToken());
        accountMap.put(token, accountBo);
        usernameMap.put(accUsername, token);

        return accountBo;
    }

    /**
     * 验证token是否有效
     *
     * @param token
     * @return
     */
    @Override
    public boolean checkTokenValid(String token) {
        AccountBo accountBo = getAccountByToken(token);
        return accountBo != null;
    }

}
